package com.hzyl.famousreader.view.widget.core;

import android.content.Context;
import android.graphics.*;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import com.blankj.utilcode.util.ConvertUtils;
import com.blankj.utilcode.util.TimeUtils;
import com.hzyl.famousreader.Constant;
import com.hzyl.famousreader.view.widget.core.animation.*;
import com.hzyl.famousreader.view.widget.core.loader.DataLoader;
import com.hzyl.famousreader.view.widget.core.loader.DataLoaderStatusEnum;
import com.hzyl.famousreader.view.widget.core.model.Page;

import java.text.SimpleDateFormat;

public class PageView extends View {

  ////////////////////////////////////////////////////////
  // 默认配置
  ////////////////////////////////////////////////////////
  private static final int DEFAULT_TIP_SIZE = 12;
  private static final int EXTRA_TITLE_SIZE = 4;

  private static final int DEFAULT_MARGIN_HEIGHT = 28;
  private static final int DEFAULT_MARGIN_WIDTH = 12;

  ////////////////////////////////////////////////////////
  // View视图
  ////////////////////////////////////////////////////////
  //View宽高
  private int mViewWidth;
  private int mViewHeight;

  //唤醒菜单的中心区域
  private RectF mCenterRect = null;

  ////////////////////////////////////////////////////////
  // 阅读参数
  ////////////////////////////////////////////////////////
  //页面背景色
  private ReadThemeEnum readTheme;
  //间距
  private int mMarginWidth;
  private int mMarginHeight;
  //标题的大小
  private int mTitleSize;
  //字体的大小
  private int mTextSize;
  //行间距
  public int mTextInterval;
  //标题的行间距
  public int mTitleInterval;
  //段落距离(基于行间距的额外距离)
  public int mTextPara;
  public int mTitlePara;

  ////////////////////////////////////////////////////////
  // 画笔
  ////////////////////////////////////////////////////////
  //绘制背景颜色的画笔(用来擦除需要重绘的部分)
  private Paint mBgPaint;
  //绘制提示的画笔
  private Paint mTipPaint;
  //绘制标题的画笔
  public Paint mTitlePaint;
  //绘制小说内容的画笔
  public TextPaint mTextPaint;
  //绘制电池的画笔
  private Paint mBatteryPaint;

  ////////////////////////////////////////////////////////
  // 书页信息
  ////////////////////////////////////////////////////////
  //当前章节列表
  //private List<BookChapter> chapters;
  ////当前显示的页
  //private Page curPage;
  ////上一章的页面列表缓存
  //private WeakReference<List<Page>> mWeakPrePageLIst;
  ////当前章节的页面列表
  //private List<Page> curPages;
  ////下一章的页面列表缓存
  //private List<Page> nextPages;

  ////////////////////////////////////////////////////////
  // 当前状态
  ////////////////////////////////////////////////////////
  //电池电量
  private int curBatteryLevel = 40;

  //翻页效果
  protected AnimModeEnum curAnimMode;
  //章节位置
  private int curChapterPos = 0;
  //当前显示模式（日间模式，夜间模式）
  private boolean curIsNightMode = true;

  ////////////////////////////////////////////////////////
  // 触摸
  ////////////////////////////////////////////////////////
  private int mStartX = 0;
  private int mStartY = 0;
  //是否翻页
  private boolean isMove = false;

  ////////////////////////////////////////////////////////
  // 监听器
  ////////////////////////////////////////////////////////
  //触摸事件回调
  private TouchListener touchListener;

  /**
   * 翻页回调
   */
  private AnimAbs.OnPageChangeListener pageChangeListener = new AnimAbs.OnPageChangeListener() {
    @Override
    public boolean prev() {
      if(!isDataLoaderPrepare) {
        return false;
      }

      boolean canPrev = dataLoader.prevPage();
      if (canPrev && animAbs instanceof HorizonAnimAbs) {
        ((HorizonAnimAbs) animAbs).switch2NoneBitmap();
      }
      return canPrev;
    }

    @Override
    public boolean next() {
      if(!isDataLoaderPrepare) {
        return false;
      }

      boolean canNext = dataLoader.nextPage();
      if (canNext && animAbs instanceof HorizonAnimAbs) {
        ((HorizonAnimAbs) animAbs).switch2NoneBitmap();
      }
      return canNext;
    }

    @Override
    public void cancel() {}
  };

  private AnimAbs animAbs;

  private boolean isUpdate = false;

  //private LoaderAbs loader;

  private DataLoader dataLoader;

  private boolean isDataLoaderPrepare = false;

  ////////////////////////////////////////////////////////
  // 绘制参数
  ////////////////////////////////////////////////////////
  private int tipMarginHeight = ConvertUtils.dp2px(3);

  //电池外框左侧位置
  private int outFrameLeft = 0;

  public PageView(Context context) {
    this(context, null);
  }

  public PageView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }

  public PageView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);

    init();
  }

  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);

    //获取View的宽高
    mViewWidth = w;
    mViewHeight = h;

    //设置中心区域
    mCenterRect = new RectF(mViewWidth / 5, mViewHeight / 3,
      mViewWidth * 4 / 5, mViewHeight * 2 / 3);

    if(isDataLoaderPrepare && dataLoader != null) {
      dataLoader.onSizeChange(w, h);
    }
    //设置翻页动画
    setAnimMode(curAnimMode);
    //在这里才调用书籍加载可以防止黑屏
    //loader.loadBook();
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    super.onTouchEvent(event);
    //if (!canTouch && event.getAction() != MotionEvent.ACTION_DOWN) return true;

    int x = (int) event.getX();
    int y = (int) event.getY();
    switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
        mStartX = x;
        mStartY = y;
        isMove = false;
        //canTouch = mTouchListener.onTouch();
        animAbs.onTouchEvent(event);
        break;
      case MotionEvent.ACTION_MOVE:
        //判断是否大于最小滑动值。
        int slop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
        if (!isMove) {
          isMove = Math.abs(mStartX - event.getX()) > slop || Math.abs(mStartY - event.getY()) > slop;
        }

        //如果滑动了，则进行翻页。
        if (isMove) {
          animAbs.onTouchEvent(event);
        }
        break;
      case MotionEvent.ACTION_UP:
        if (!isMove) {
          //是否点击了中间
          if (mCenterRect.contains(x, y)) {
            if (touchListener != null) {
              touchListener.center();
            }
            return true;
          }
        }
        animAbs.onTouchEvent(event);
        break;
    }
    return true;
  }

  @Override
  public void computeScroll() {
    //mPageAnim.scrollAnim();
    animAbs.scrollAnim();
    super.computeScroll();
  }

  @Override
  protected void onDraw(Canvas canvas) {

    //绘制背景：背景色、电池电量、时间
    drawBackground(animAbs.getBgBitmap());

    //绘制书籍内容
    drawContent(animAbs.getShowBitmap());

    //绘制翻页动画
    animAbs.draw(canvas);
  }

  ///////////////////////////////////////////////////////////////////////////////
  //  功能区
  ///////////////////////////////////////////////////////////////////////////////

  public void notifyChapterIsExit(int chapter) {
    dataLoader.notifyChapterIsExit(chapter);
  }

  /**
   * 进入上一章
   */
  public void prevChapter() {
    if(isDataLoaderPrepare) {
      dataLoader.prevChapter();
      this.invalidate();
    }
  }

  /**
   * 进入下一章
   */
  public void nextChapter() {
    if(isDataLoaderPrepare) {
      dataLoader.nextChapter();
      this.invalidate();
    }
  }

  /**
   * 跳转章节
   * @param position
   */
  public void skipChapter(int position) {
    if(isDataLoaderPrepare) {
      dataLoader.skipToChapter(position);
      this.invalidate();
    }
  }

  ///////////////////////////////////////////////////////////////////////////////
  //  阅读参数设置
  ///////////////////////////////////////////////////////////////////////////////
  public void setDataLoader(DataLoader dataLoader) {
    isDataLoaderPrepare = false;
    this.dataLoader = dataLoader;
    this.dataLoader.setPageView(this);
    this.dataLoader.onSizeChange(mViewWidth, mViewHeight);
    this.dataLoader.init();
    isDataLoaderPrepare = true;
    this.invalidate();
  }

  /**
   * 通知更新电池电量
   *
   * @param level
   */
  public void updateBattery(int level) {
    this.curBatteryLevel = level;
    invalidate();
  }

  /**
   * 通知更新时间
   */
  public void updateTime() {
    invalidate();
  }

  /**
   * 设置阅读的字体大小
   *
   * @param size
   */
  public void setTextSize(int size) {
    //存储状态
    ReadSettingManager.setTextSize(size);

    //设置textSize
    mTextSize = size;
    mTextInterval = mTextSize / 2;
    mTextPara = mTextSize;

    mTitleSize = mTextSize + ConvertUtils.sp2px(EXTRA_TITLE_SIZE);
    mTitleInterval = mTitleInterval / 2;
    mTitlePara = mTitleSize;

    //设置画笔的字体大小
    mTextPaint.setTextSize(mTextSize);
    //设置标题的字体大小
    mTitlePaint.setTextSize(mTitleSize);

    if(isDataLoaderPrepare) {
      dataLoader.reload();
    }

    invalidate();
  }

  /**
   * 设置翻页动画
   *
   * @param animMode
   */
  public void setAnimMode(AnimModeEnum animMode) {
    curAnimMode = animMode;
    ReadSettingManager.setAnimMode(animMode);
    switch (animMode) {
      case NONE:
        animAbs = new NoneAnim(this, mViewWidth, mViewHeight, pageChangeListener);
        break;
      case SIMULATION:
        animAbs = new SimulationAnim(this, mViewWidth, mViewHeight, pageChangeListener);
        break;
      case COVER:
        animAbs = new CoverAnim(this, mViewWidth, mViewHeight, pageChangeListener);
        break;
      case SLIDE:
        animAbs = new SlideAnim(this, mViewWidth, mViewHeight, pageChangeListener);
        break;
      case SCROLL:
        animAbs = new ScrollAnim(this, mViewWidth, mViewHeight, 0, ConvertUtils.dp2px(DEFAULT_MARGIN_HEIGHT), pageChangeListener);
        break;
      default:
        animAbs = new SimulationAnim(this, mViewWidth, mViewHeight, pageChangeListener);
    }
    if(animAbs instanceof HorizonAnimAbs) {
      ((HorizonAnimAbs) animAbs).switch2NoneBitmap();
      invalidate();
      ((HorizonAnimAbs) animAbs).switch2NoneBitmap();
      invalidate();
    }
  }

  /**
   * 日间/夜间模式切换
   *
   * @return true-夜间模式 false-日间模式
   */
  public boolean toggleNightMode() {
    setNightMode(!curIsNightMode);
    return curIsNightMode;
  }

  /**
   * 设置日间/夜间模式
   *
   * @param bool
   */
  public void setNightMode(boolean bool) {
    curIsNightMode = bool;
    ReadSettingManager.setNightMode(bool);

    if (curIsNightMode) {
      mBatteryPaint.setColor(Color.WHITE);
    } else {
      mBatteryPaint.setColor(Color.BLACK);
    }

    ReadThemeEnum theme = bool ? ReadThemeEnum.NIGHT : ReadSettingManager.getReadTheme();
    setReadTheme(theme);
  }

  /**
   * 设置阅读的颜色主题
   *
   * @param theme
   */
  public void setReadTheme(ReadThemeEnum theme) {
    readTheme = theme;
    if (!curIsNightMode) {
      ReadSettingManager.setReadTheme(theme);
    }
    mBgPaint.setColor(readTheme.getBgColor());
    mBatteryPaint.setColor(readTheme.getTextColor());
    mTextPaint.setColor(readTheme.getTextColor());
    mTipPaint.setColor(readTheme.getTextColor());
    mTitlePaint.setColor(readTheme.getTextColor());
    this.invalidate();
  }

  /**
   * 设置触摸事件监听器
   *
   * @param touchListener
   */
  public void setOnTouchListener(TouchListener touchListener) {
    this.touchListener = touchListener;
  }

  ///////////////////////////////////////////////////////////////////////////////
  //  阅读参数获取
  ///////////////////////////////////////////////////////////////////////////////
  /**
   * 获取字体大小
   * @return
   */
  public int getTextSize() {
    return mTextSize;
  }

  /**
   * 当前是否夜间模式
   *
   * @return true-是 false-不是
   */
  public boolean isNightMode() {
    return curIsNightMode;
  }

  /**
   * 获取当前章节总页数
   *
   * @return
   */
  public int getPageSize() {
    if(isDataLoaderPrepare) {
      return dataLoader.getCurPagesSize();
    }
    return 0;
  }

  ///////////////////////////////////////////////////////////////////////////////
  //  视图绘制
  ///////////////////////////////////////////////////////////////////////////////
  /**
   * 初始化
   */
  private void init() {

    //阅读参数
    mTextSize = ReadSettingManager.getTextSize();
    mTitleSize = mTextSize + ConvertUtils.sp2px(EXTRA_TITLE_SIZE);
    curAnimMode = ReadSettingManager.getAnimMode();
    curIsNightMode = ReadSettingManager.isNightMode();
    readTheme = ReadSettingManager.getReadTheme();

    mMarginWidth = ConvertUtils.dp2px(DEFAULT_MARGIN_WIDTH);
    mMarginHeight = ConvertUtils.dp2px(DEFAULT_MARGIN_HEIGHT);
    mTextInterval = mTextSize / 2;
    mTitleInterval = mTitleSize / 2;
    mTextPara = mTextSize; //段落间距由 text 的高度决定。
    mTitlePara = mTitleSize;

    //绘制背景的画笔
    mBgPaint = new Paint();
    mBgPaint.setColor(readTheme.getBgColor());

    //绘制电池的画笔
    mBatteryPaint = new Paint();
    mBatteryPaint.setAntiAlias(true);
    mBatteryPaint.setDither(true);
    if (curIsNightMode) {
      mBatteryPaint.setColor(Color.WHITE);
    } else {
      mBatteryPaint.setColor(Color.BLACK);
    }

    //绘制提示的画笔
    mTipPaint = new Paint();
    mTipPaint.setColor(readTheme.getTextColor());
    mTipPaint.setTextAlign(Paint.Align.LEFT);//绘制的起始点
    mTipPaint.setTextSize(ConvertUtils.sp2px(DEFAULT_TIP_SIZE));//Tip默认的字体大小
    mTipPaint.setAntiAlias(true);
    mTipPaint.setSubpixelText(true);

    //绘制标题的画笔
    mTitlePaint = new TextPaint();
    mTitlePaint.setColor(readTheme.getTextColor());
    mTitlePaint.setTextSize(mTitleSize);
    mTitlePaint.setStyle(Paint.Style.FILL_AND_STROKE);
    mTitlePaint.setTypeface(Typeface.DEFAULT_BOLD);
    mTitlePaint.setAntiAlias(true);

    //绘制页面内容的画笔
    mTextPaint = new TextPaint();
    mTextPaint.setColor(readTheme.getTextColor());
    mTextPaint.setTextSize(mTextSize);
    mTextPaint.setAntiAlias(true);
  }

  /**
   * 绘制页面背景（时间、电量、左上角章节标题、左下角页码）
   */
  private void drawBackground(Bitmap bitmap) {
    Canvas canvas = new Canvas(bitmap);
    //绘制背景色
    canvas.drawColor(readTheme.getBgColor());
    drawBattery(canvas);
    drawTime(canvas);

    if(isDataLoaderPrepare) {
      drawChapterTitle(canvas);
      drawChapterPage(canvas);
    }
  }

  /**
   * 绘制电池
   */
  private void drawBattery(Canvas canvas) {
    int visibleRight = mViewWidth - mMarginWidth;
    int visibleBottom = mViewHeight - tipMarginHeight;

    int outFrameWidth = (int) mTipPaint.measureText("xxx");
    int outFrameHeight = (int) mTipPaint.getTextSize();

    int polarHeight = ConvertUtils.dp2px(6);
    int polarWidth = ConvertUtils.dp2px(2);
    int border = 1;
    int innerMargin = 1;

    //电极的制作
    int polarLeft = visibleRight - polarWidth;
    int polarTop = visibleBottom - (outFrameHeight + polarHeight) / 2;
    Rect polar = new Rect(polarLeft, polarTop, visibleRight,
      polarTop + polarHeight - ConvertUtils.dp2px(2));

    mBatteryPaint.setStyle(Paint.Style.FILL);
    canvas.drawRect(polar, mBatteryPaint);

    //外框的制作
    outFrameLeft = polarLeft - outFrameWidth;
    int outFrameTop = visibleBottom - outFrameHeight;
    int outFrameBottom = visibleBottom - ConvertUtils.dp2px(2);
    Rect outFrame = new Rect(outFrameLeft, outFrameTop, polarLeft, outFrameBottom);

    mBatteryPaint.setStyle(Paint.Style.STROKE);
    mBatteryPaint.setStrokeWidth(border);
    canvas.drawRect(outFrame, mBatteryPaint);

    //内框的制作
    float innerWidth = (outFrame.width() - innerMargin * 2 - border) * (curBatteryLevel / 100.0f);
    RectF innerFrame = new RectF(outFrameLeft + border + innerMargin, outFrameTop + border + innerMargin,
      outFrameLeft + border + innerMargin + innerWidth, outFrameBottom - border - innerMargin);

    mBatteryPaint.setStyle(Paint.Style.FILL);
    canvas.drawRect(innerFrame, mBatteryPaint);
  }

  /**
   * 绘制当前时间
   */
  private void drawTime(Canvas canvas) {
    //底部的字显示的位置Y
    float y = mViewHeight - mTipPaint.getFontMetrics().bottom - tipMarginHeight;
    String time = TimeUtils.millis2String(System.currentTimeMillis(), new SimpleDateFormat(Constant.FORMAT_TIME));
    float x = outFrameLeft - mTipPaint.measureText(time) - ConvertUtils.dp2px(4);
    canvas.drawText(time, x, y, mTipPaint);
  }

  /**
   * 绘制章节标题
   */
  private void drawChapterTitle(Canvas canvas) {
    //需要注意的是:绘制text的y的起始点是text的基准线的位置，而不是从text的头部的位置
    float tipTop = tipMarginHeight - mTipPaint.getFontMetrics().top;
    //根据状态不一样，数据不一样
    if(dataLoader.getLoadStatus() == DataLoaderStatusEnum.FINISH) {
      canvas.drawText(dataLoader.getChapterTitle(), mMarginWidth, tipTop, mTipPaint);
    } else {
      if (dataLoader.getChapters() != null && dataLoader.getChapters().size() != 0) {
        canvas.drawText(dataLoader.getChapterTitle(), mMarginWidth, tipTop, mTipPaint);
      }
    }
  }

  /**
   * 绘制章节页码
   */
  private void drawChapterPage(Canvas canvas) {
    //底部的字显示的位置Y
    float y = mViewHeight - mTipPaint.getFontMetrics().bottom - tipMarginHeight;
    //只有finish的时候采用页码
    if (dataLoader.getLoadStatus() == DataLoaderStatusEnum.FINISH) {
      String percent = dataLoader.getCurPagePosition() + "/" + dataLoader.getCurPagesSize();
      canvas.drawText(percent, mMarginWidth, y, mTipPaint);
    }
  }

  /**
   * 绘制阅读内容
   */
  private void drawContent(Bitmap bitmap) {
    Canvas canvas = new Canvas(bitmap);

    if (curAnimMode == AnimModeEnum.SCROLL) {
      canvas.drawColor(readTheme.getBgColor());
    }

    if(!isDataLoaderPrepare) {
      //绘制字体
      String tip = "还没获取到书籍数据，请耐心等待";

      //将提示语句放到正中间
      Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
      float textHeight = fontMetrics.top - fontMetrics.bottom;
      float textWidth = mTextPaint.measureText(tip);
      float pivotX = (mViewWidth - textWidth) / 2;
      float pivotY = (mViewHeight - textHeight) / 2;
      canvas.drawText(tip, pivotX, pivotY, mTextPaint);
      return;
    }

    if(dataLoader.getLoadStatus() == DataLoaderStatusEnum.FINISH) {
      float top;

      if (curAnimMode == AnimModeEnum.SCROLL) {
        top = -mTextPaint.getFontMetrics().top;
      } else {
        top = mMarginHeight - mTextPaint.getFontMetrics().top;
      }

      //设置总距离
      int interval = mTextInterval + (int) mTextPaint.getTextSize();
      int para = mTextPara + (int) mTextPaint.getTextSize();
      int titleInterval = mTitleInterval + (int) mTitlePaint.getTextSize();
      int titlePara = mTitlePara + (int) mTextPaint.getTextSize();
      String str = null;

      Page curPage = dataLoader.getCurPage();
      //对标题进行绘制
      for (int i = 0; i < curPage.getTitleLines(); ++i) {
        str = curPage.getLines().get(i);

        //设置顶部间距
        if (i == 0) {
          top += mTitlePara;
        }

        //计算文字显示的起始点
        int start = (int) (mViewWidth - mTitlePaint.measureText(str)) / 2;
        //进行绘制
        canvas.drawText(str, start, top, mTitlePaint);

        //设置尾部间距
        if (i == curPage.getTitleLines() - 1) {
          top += titlePara;
        } else {
          //行间距
          top += titleInterval;
        }
      }

      //对内容进行绘制
      for (int i = curPage.getTitleLines(); i < curPage.getLines().size(); ++i) {
        str = curPage.getLines().get(i);

        canvas.drawText(str, mMarginWidth, top, mTextPaint);
        if (str.endsWith("\n")) {
          top += para;
        } else {
          top += interval;
        }
      }
    } else {
      //绘制字体
      String tip = "";
      switch (dataLoader.getLoadStatus()) {
        case LOADING:
          tip = "正在拼命加载中...";
          break;
        case ERROR:
          tip = "加载失败(点击边缘重试)";
          break;
        case EMPTY:
          tip = "文章内容为空";
          break;
      }

      //将提示语句放到正中间
      Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
      float textHeight = fontMetrics.top - fontMetrics.bottom;
      float textWidth = mTextPaint.measureText(tip);
      float pivotX = (mViewWidth - textWidth) / 2;
      float pivotY = (mViewHeight - textHeight) / 2;
      canvas.drawText(tip, pivotX, pivotY, mTextPaint);
    }
  }

  ///////////////////////////////////////////////////////
  //  事件回调接口
  ///////////////////////////////////////////////////////

  /**
   * 触摸事件监听器
   */
  public interface TouchListener {

    /**
     * 触摸中心区域回调
     */
    void center();
  }
}
